package com.lanyou.esb.cook.proxy.redis.proxy.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.lanyou.esb.cook.proxy.redis.JedisPoolUtils;
import com.lanyou.esb.cook.proxy.redis.RedisLock;
import com.lanyou.esb.cook.proxy.redis.proxy.base.BaseJedisProxy;
import com.lanyou.esb.cook.proxy.redis.vo.Group;
import com.lanyou.esb.cook.proxy.vo.EntityGroup;

/**
 * Redis批量操作代理
 * 
 * @author Davey.wu
 */
public class RedisBatchProxy extends BaseJedisProxy<EntityGroup> {

	@Override
	public String getKeyFromObject(EntityGroup target) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 批量读取redis数据
	 * 
	 * @param group
	 *            ：查询条件组合
	 * @return
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws JedisException
	 * @throws IOException
	 */
	public Map<Class, Object> batchGet(Group group) throws JsonParseException,
			JsonMappingException, JedisException, IOException {
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		// HASH类型数据查询条件
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> hashs = group
				.getHashs();
		// STRING类型数据查询条件
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> strs = group
				.getStrs();
		Map<Class, Response<String>> responses = new HashMap<>();
		boolean broken = false;
		try {
			// 通过管道批量执行查询命令
			Pipeline p = jedis.pipelined();
			// 获取HASH类型数据
			if (hashs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : hashs) {
					responses.put(entry.getClasses(),
							p.hget(entry.getKey(), entry.getField()));
				}
			}
			// 获取STRING类型数据
			if (strs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : strs) {
					responses.put(entry.getClasses(), p.get(entry.getKey()));
				}
			}
			p.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		if (responses.isEmpty()) {
			return null;
		}
		Map<Class, Object> result = new HashMap<>(responses.size());
		// 转换结果集
		// HASH数据类型结果转换
		if (hashs != null) {
			for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : hashs) {
				String value = responses.get(entry.getClasses()) != null ? responses
						.get(entry.getClasses()).get() : "";
				// 判断是否需要将JSON字符串转换成对象
				if (StringUtils.isNotBlank(value) && entry.isConvert()) {
					result.put(entry.getClasses(),
							BaseJedisProxy.fromJson(value, entry.getClasses()));
					continue;
				}
				result.put(entry.getClasses(), value);
			}
		}
		// STRING数据类型结果转换
		if (strs != null) {
			for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : strs) {
				String value = responses.get(entry.getClasses()) != null ? responses
						.get(entry.getClasses()).get() : "";
				// 判断是否需要将JSON字符串转换成对象
				if (StringUtils.isNotBlank(value) && entry.isConvert()) {
					result.put(entry.getClasses(),
							BaseJedisProxy.fromJson(value, entry.getClasses()));
					continue;
				}
				result.put(entry.getClasses(), value);
			}
		}
		return result;
	}

	/**
	 * 批量设置redis数据
	 * 
	 * @param group
	 * @return
	 */
	public boolean batchSet(Group group) {
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return false;
		}

		// hash类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> hashs = group
				.getHashs();
		// string类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> strs = group
				.getStrs();
		// set类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> sets = group
				.getSets();
		// list类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> lists = group
				.getLists();
		boolean broken = false;
		boolean result = false;
		try {
			// 通过管道批量执行查询命令
			Pipeline p = jedis.pipelined();
			// 获取hash类型数据
			if (hashs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : hashs) {
					p.hset(entry.getKey(), entry.getField(), entry.getValue());
				}
			}
			// 获取set类型数据
			if (sets != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : sets) {
					p.sadd(entry.getKey(), entry.getValue());
				}
			}
			// 获取list类型数据
			if (lists != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : lists) {
					p.rpush(entry.getKey(), entry.getValue());
				}
			}
			// 获取string类型数据
			if (strs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : strs) {
					switch (entry.getType()) {
					case INCR:
						p.incr(entry.getKey());
						break;
					case INCR_BY:
						p.incrBy(entry.getKey(),
								Integer.parseInt(entry.getValue()));
						break;
					case INCR_BY_FLOAT:
						p.incrByFloat(entry.getKey(),
								Double.parseDouble(entry.getValue()));
						break;
					default:
						p.set(entry.getKey(), entry.getValue());
					}
					// 设置超时时长
					p.expire(entry.getKey(), entry.getTimeOut());
				}
			}
			p.sync();
			result = true;
		} catch (Exception e) {
			result = false;
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}

	/**
	 * 批量设置redis数据,加事务控制
	 * 
	 * @param group
	 * @return
	 */
	public boolean batchSetTransaction(Group group) {
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return false;
		}

		// hash类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> hashs = group
				.getHashs();
		// string类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> strs = group
				.getStrs();
		// set类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> sets = group
				.getSets();
		// list类型数据
		List<com.lanyou.esb.cook.proxy.redis.vo.Group.Entry> lists = group
				.getLists();
		boolean broken = false;
		boolean result = false;
		boolean lock = StringUtils.isNotBlank(group.getLock());
		try {
			// 加锁
			if (lock) {
				RedisLock.lock(jedis, group.getLock(), 2l);
			}
			// 对LIST类型数据进行过滤，以消除重复记录,start===============
			if (lists != null && !lists.isEmpty()) {
				for (int i = lists.size() - 1; i >= 0; --i) {
					if (StringUtils.isBlank(lists.get(i).getFilter())) {
						continue;
					}
					// 判断键是否已存在，已存在则过滤
					if (true == jedis.exists(lists.get(i).getFilter())) {
						lists.remove(i);
					}
				}
			}
			// 对LIST类型数据进行过滤，以消除重复记录,end===============

			// 通过管道批量执行查询命令
			// Pipeline p = jedis.pipelined();
			Transaction transaction = jedis.multi();
			// 获取hash类型数据
			if (hashs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : hashs) {
					transaction.hset(entry.getKey(), entry.getField(),
							entry.getValue());
				}
			}
			// 获取set类型数据
			if (sets != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : sets) {
					transaction.sadd(entry.getKey(), entry.getValue());
				}
			}
			// 获取list类型数据
			if (lists != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : lists) {
					transaction.rpush(entry.getKey(), entry.getValue());
				}
			}
			// 获取string类型数据
			if (strs != null) {
				for (com.lanyou.esb.cook.proxy.redis.vo.Group.Entry entry : strs) {
					switch (entry.getType()) {
					case INCR:
						transaction.incr(entry.getKey());
						break;
					case INCR_BY:
						transaction.incrBy(entry.getKey(),
								Integer.parseInt(entry.getValue()));
						break;
					case INCR_BY_FLOAT:
						transaction.incrByFloat(entry.getKey(),
								Double.parseDouble(entry.getValue()));
						break;
					default:
						transaction.set(entry.getKey(), entry.getValue());
					}
					// 设置超时时长
					transaction.expire(entry.getKey(), entry.getTimeOut());
				}
			}
			transaction.exec();
			result = true;
		} catch (Exception e) {
			result = false;
			broken = true;
		} finally {
			// 解锁
			if (lock) {
				try {
					RedisLock.unlock(jedis, group.getLock());
				} finally {
				}
			}
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}
}
